﻿/* ****************************************************************************
 *
 * Copyright (c) Microsoft Corporation. 
 *
 * This source code is subject to terms and conditions of the Microsoft Public License. A
 * copy of the license can be found at http://go.microsoft.com/fwlink/?LinkID=131993. If
 * you cannot locate the Microsoft Public License, please send an email to
 * mixon@microsoft.com. By using this source code in any fashion, you are agreeing to
 * be bound by the terms of the Microsoft Public License.
 *
 * You must not remove this notice, or any other, from this software.
 *
 *
 * ***************************************************************************/

using System;
using System.IO;
using System.IO.IsolatedStorage;
using System.Runtime.Serialization;
using System.Windows.Controls;

namespace MIXOnline.Descry
{

    /// <summary>
    /// A handy class that wraps up some of the more common Isolated Storage access functions.
    /// </summary>
    public class Storage
    {
        public static void WriteStringToFile(string input, string filename)
        {
            IsolatedStorageFile isf = IsolatedStorageFile.GetUserStoreForApplication();
            IsolatedStorageFileStream stream = new IsolatedStorageFileStream(filename, System.IO.FileMode.OpenOrCreate, isf);
            StreamWriter sw = new StreamWriter(stream);
            sw.Write(input);
            sw.Close();
        }

        public static string ConvertObjectToString<T>(T obj)
        {
            DataContractSerializer ser = new DataContractSerializer(typeof(T));
            MemoryStream ms = new MemoryStream();
            ser.WriteObject(ms, obj);
            return Convert.ToBase64String(ms.ToArray());
        }

        public static Stream ConvertObjectToStream<T>(T obj)
        {
            DataContractSerializer ser = new DataContractSerializer(typeof(T));
            MemoryStream ms = new MemoryStream();
            ser.WriteObject(ms, obj);
            return ms;
        }

        public static T ConvertStringToObject<T>(string s)
        {
            if (string.IsNullOrEmpty(s)) return default(T); //instead of null for generic types

            DataContractSerializer ser = new DataContractSerializer(typeof(T));
            MemoryStream ms = new MemoryStream(Convert.FromBase64String(s));
            return (T)ser.ReadObject(ms);
        }

        public static T ConvertStreamToObject<T>(Stream s)
        {
            if (s.Length == 0) return default(T); //instead of null for generic types

            DataContractSerializer ser = new DataContractSerializer(typeof(T));

            T obj = (T)ser.ReadObject(s);

            s.Close();

            return obj;
        }

        /// <summary>
        /// Saves an object to Isolated Storage per application.
        /// </summary>
        /// <typeparam name="T">Type of object</typeparam>
        /// <param name="obj">The object to be serialized.</param>
        /// <param name="filename">The name of the file the serialized object is saved to.</param>
        /// <returns>How much Isolated quota needs to be increased for this save.</returns>
        public static long WriteObjectToStorage<T>(T obj, string filename)
        {
            Stream s = ConvertObjectToStream<T>(obj);
            WriteStreamToFile(filename, s);

            s.Close();

            return 0; // TODO: Implement this to return how much space we need if call fails
        }

        public static T ReadObjectFromStorage<T>(string filename)
        {
            if (FileExists(filename))
            {
                Stream s = ReadStreamFromFile(filename);
                return (T)Storage.ConvertStreamToObject<T>(s);
            }
            else
                return default(T);

        }

        static public bool FileExists(string filename)
        {
            IsolatedStorageFile isf = IsolatedStorageFile.GetUserStoreForApplication();
            return isf.FileExists(filename);
        }

        /// <summary>
        /// Deletes a file from Isolated Storage if it exists
        /// </summary>
        /// <param name="filename">filename</param>
        /// <returns>true if file existed</returns>
        static public bool DeleteFile(string filename)
        {
            IsolatedStorageFile isf = IsolatedStorageFile.GetUserStoreForApplication();

            if (FileExists(filename))
            {
                try
                {
                    isf.DeleteFile(filename);
                }
                catch (Exception e)
                {
                    throw new Exception("unable to delete file");
                }
                return true;
            }
            return false;
        }

        static public void SetAppSettingItem(string KeyName, object Item)
        {
            IsolatedStorageSettings.ApplicationSettings[KeyName] = Item;
            IsolatedStorageSettings.ApplicationSettings.Save();
        }

        static public object GetAppSettingItem(string KeyName)
        {
            if (IsolatedStorageSettings.ApplicationSettings.Contains(KeyName))
                return IsolatedStorageSettings.ApplicationSettings[KeyName] as object;
            else
                return null;
        }


        static public string FileToString(string filename)
        {
            string filecontents = string.Empty;
            IsolatedStorageFile isf = IsolatedStorageFile.GetUserStoreForApplication();
            IsolatedStorageFileStream stream = new IsolatedStorageFileStream(filename, System.IO.FileMode.OpenOrCreate, isf);
            StreamReader sr = new System.IO.StreamReader(stream);
            filecontents = sr.ReadToEnd(); //slow
            
            sr.Close();

            return filecontents;
        }

        static public Stream ReadStreamFromFile(string filename)
        {
            //string filecontents = string.Empty;
            IsolatedStorageFile isf = IsolatedStorageFile.GetUserStoreForApplication();
            return new IsolatedStorageFileStream(filename, System.IO.FileMode.OpenOrCreate, isf);
        }

        static public void WriteStreamToFile(string filename, Stream s)
        {
            s.Position = 0;
            IsolatedStorageFile isf = IsolatedStorageFile.GetUserStoreForApplication();

            // Open or create a writable file.
            IsolatedStorageFileStream isoStream =
                new IsolatedStorageFileStream(filename,
                FileMode.OpenOrCreate,
                FileAccess.Write, isf);

            byte[] ba = new byte[s.Length];
            s.Read(ba, 0, (int)s.Length);
            isoStream.Write(ba, 0, (int)s.Length);
            isoStream.Close();
            s.Close();
        }

        static public OpenFileDialog ShowGenericOpenFileDialog()
        {
            var ofd = new OpenFileDialog();
            ofd.Multiselect = false;
            ofd.Filter = "All Files|*.*";
            ofd.FilterIndex = 1;

            ofd.ShowDialog();

            return ofd;
        }

        static public string GetFileAsString(OpenFileDialog ofd)
        {
            string filecontents = string.Empty;
            System.IO.FileInfo fdi = ofd.File;

            if (fdi != null)
            {
                StreamReader sr = fdi.OpenText();
                filecontents = sr.ReadToEnd();
                sr.Close();
            }
            return filecontents;
        }

        // increase the host's quota of storage space on the local computer. 
        static public string IncreaseQuota(Int64 spaceToAddInBytes)
        {
            // Obtain an isolated store for an application.
            try
            {
                using (var store = IsolatedStorageFile.GetUserStoreForApplication())
                {
                    Int64 curAvail = store.AvailableFreeSpace;

                    // If available space is less than what is requested, try to increase.
                    if (curAvail < spaceToAddInBytes)
                    {
                        // Request more quota space.
                        if (!store.IncreaseQuotaTo(store.Quota + spaceToAddInBytes))
                        {
                            return "Increase rejected.";
                        }
                        else
                        {
                            return "Increase approved.";
                        }
                    }
                    else
                    {
                        return curAvail.ToString() + "is still available.";
                    }
                }
            }

            catch (IsolatedStorageException ex)
            {
                return ex.Message;
            }
        }

        static public long GetCurrentQuota()
        {
            using (var store = IsolatedStorageFile.GetUserStoreForApplication())
            {
                return store.Quota;
            }
        }
    }
}
